package com.echovin.esb.gateway.locator;

import com.echovin.esb.gateway.model.GatewayIPLimitApi;
import com.echovin.esb.gateway.service.GatewayIPLimitService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class GatewayIPLimitResourceLocator {
    private Map<String, List<String>> IPBlackResourceMap = new ConcurrentHashMap<>();
    private Map<String, List<String>> IPWhiteResourceMap = new ConcurrentHashMap<>();

    @Autowired
    GatewayIPLimitService gatewayIPLimitService;
    @Autowired
    GatewayServiceResourceLocator gatewayServiceResourceLocator;

    public GatewayIPLimitResourceLocator() {
    }

    /**
     * 清空缓存并刷新
     */
    public void refresh() {
        this.getIPBlackResource();
        this.getIPWhiteResource();
    }
    /**
     * ip匹配黑名单
     */
    public boolean matchIpBlacklist(String requestPath, String ipAddress) {
        return this.matchIpBlackOrWhitelist(requestPath, ipAddress, IPBlackResourceMap);
    }
    /**
     * ip匹配白名单
     */
    public boolean matchIpWhitelist(String requestPath, String ipAddress) {
        return this.matchIpBlackOrWhitelist(requestPath, ipAddress, IPWhiteResourceMap);
    }
    /**
     * ip匹配黑/白名单
     */
    private boolean matchIpBlackOrWhitelist(String requestPath, String ipAddress, Map<String, List<String>> source) {
        if (StringUtils.isEmpty(requestPath) || StringUtils.isEmpty(ipAddress)) {
            return false;
        }
        String serviceId = gatewayServiceResourceLocator.getServiceId(requestPath);
        if (StringUtils.isEmpty(serviceId)) {
            return false;
        }
        List<String> ips = source.get(serviceId);
        if (ips == null) {
            return false;
        }
        return ips.stream().filter(r -> r.equals(ipAddress)).findFirst().isPresent();
    }
    /**
     * 拿到该url对应的黑名单
     * @return
     */
    private void getIPBlackResource() {
        IPBlackResourceMap.clear();
        IPBlackResourceMap.putAll(loadResourceDefine(1));
    }
    /**
     * 拿到该url对应的白名单
     * @return
     */
    private void getIPWhiteResource() {
        IPWhiteResourceMap.clear();
        IPWhiteResourceMap.putAll(loadResourceDefine(2));
    }

    /**
     * 调用service查询所有的服务id与ip黑/白名单对应关系，组装{serviceid：[ips]}
     */
    private Map<String, List<String>> loadResourceDefine(Integer policyType) {
        Map<String, List<String>> map = new ConcurrentHashMap<>();
        try {
            List<GatewayIPLimitApi> resourceList = gatewayIPLimitService.findIpLimitApiList(policyType);
            if (resourceList == null) {
                return map;
            }

            Iterator var3 = resourceList.iterator();
            while(var3.hasNext()) {
                GatewayIPLimitApi resource = (GatewayIPLimitApi)var3.next();
                List<String> atts = map.get(resource.getServiceId());
                if (atts == null) {
                    atts = new ArrayList();
                }
                // ","拆分ip段
                String[] ips = (resource.getIpAddress()).split(",");
                for (String ip : ips) {
                    if (!atts.contains(ip)) {
                        atts.add(ip);
                    }
                }
                map.put(resource.getServiceId(), atts);
            }

        } catch (Exception e) {
            log.error("加载ip黑/白名单错误:{}", e);
        }

        if (policyType == 1) {
            log.info("数据库加载ip黑名单{}", map);
        } else if (policyType == 2) {
            log.info("数据库加载ip白名单{}", map);
        }

        return map;
    }
}
